#include <iostream>
#include <chrono>
#include "gf2m.h"

using namespace std;
using namespace chrono;
using namespace GF2M;

int main() {
    unsigned int m;

    m = 2000;

    GF2M_MATRIX<unsigned char> A(m, m, GF2M_MATRIX_TYPE::GF2M_MATRIX_UTRIANGLE), B(m, m, GF2M_MATRIX_TYPE::GF2M_MATRIX_LTRIANGLE);
    GF2M_MATRIX<unsigned char> C, D, E;

    /*cout<<"A:"<<endl;
    for(unsigned int i = 0; i < A.getRows(); i++) {
        for(unsigned int j = 0; j < A.getCols(); j++) {
            cout<<A.get(i, j);
        }
        cout<<endl;
    }

    cout<<"B:"<<endl;
    for(unsigned int i = 0; i < B.getRows(); i++) {
        for(unsigned int j = 0; j < B.getCols(); j++) {
            cout<<B.get(i, j);
        }
        cout<<endl;
    }*/


    {
        cout << "C = A * B" << endl;

        auto start = system_clock::now();
        C = A * B;
        auto end = system_clock::now();

        auto duration = duration_cast<microseconds>(end - start);

        /*cout << "C:" << endl;
        for (unsigned int i = 0; i < C.getRows(); i++) {
            for (unsigned int j = 0; j < C.getCols(); j++) {
                cout << C.get(i, j);
            }
            cout << endl;
        }*/

        cout << "Matrix Size: " << C.getRows() << "x" << C.getCols() << endl;
        cout << "Multiplication Operation took: "
             << double(duration.count()) * microseconds::period::num / microseconds::period::den
             << " seconds" << endl;
    }

    {
        cout<<"D = A'"<<endl;

        auto start = system_clock::now();

        D = A.Trans();

        auto end = system_clock::now();

        auto duration = duration_cast<microseconds>(end - start);

        /*cout<<"D:"<<endl;
        for(unsigned int i = 0; i < D.getRows(); i++) {
            for(unsigned int j = 0; j < D.getCols(); j++) {
                cout<<D.get(i, j);
            }
            cout<<endl;
        }*/

        cout<<"Matrix Size: "<<D.getRows()<<"x"<<D.getCols()<<endl;
        cout<<"Trans Operation took: "
            <<double(duration.count()) * microseconds::period::num / microseconds::period::den
            <<" seconds"<<endl;
    }

    {
        cout<<"E = 1/A"<<endl;

        auto start = system_clock::now();

        E = 1/A;

        auto end = system_clock::now();

        auto duration = duration_cast<microseconds>(end - start);

        /*cout<<"E:"<<endl;
        for(unsigned int i = 0; i < E.getRows(); i++) {
            for(unsigned int j = 0; j < E.getCols(); j++) {
                cout<<E.get(i, j);
            }
            cout<<endl;
        }*/

        cout<<"Matrix Size: "<<E.getRows()<<"x"<<E.getCols()<<endl;
        cout<<"Inversion Operation took: "
            <<double(duration.count()) * microseconds::period::num / microseconds::period::den
            <<" seconds"<<endl;
    }

    return 0;
}
